package com.macro.mall.tiny.modules.foster.service.impl;

import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.macro.mall.tiny.common.api.CommonResult;
import com.macro.mall.tiny.modules.foster.mapper.AppointmentMapper;
import com.macro.mall.tiny.modules.foster.mapper.PetMapper;
import com.macro.mall.tiny.modules.foster.mapper.PetStatusMapper;
import com.macro.mall.tiny.modules.foster.mapper.UserMapper;
import com.macro.mall.tiny.modules.foster.model.Appointment;
import com.macro.mall.tiny.modules.foster.model.Pet;
import com.macro.mall.tiny.modules.foster.model.PetStatus;
import com.macro.mall.tiny.modules.foster.model.User;
import com.macro.mall.tiny.modules.foster.model.domain.AdminUserDetails;
import com.macro.mall.tiny.modules.foster.model.dto.PetAndTimeDTO;
import com.macro.mall.tiny.modules.foster.service.PetService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;
import java.util.Map;

import static com.baomidou.mybatisplus.core.toolkit.IdWorker.getId;


/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author zhuyi
 * @since 2024-03-27
 */
@Service
public class PetServiceImpl extends ServiceImpl<PetMapper, Pet> implements PetService {

    private static final Logger LOGGER = LoggerFactory.getLogger(PetServiceImpl.class);

    @Autowired
    private AppointmentMapper appointmentMapper;

    @Autowired
    private PetMapper petMapper;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private PetStatusMapper petStatusMapper;

    /**
     * 添加宠物信息和预约信息
     *
     * @param petAndTimeDTO 包含宠物信息和预约时间信息的数据传输对象。其中，petAndTimeDTO包含一个Pet对象和预约的开始时间、结束时间以及房间ID。
     * @return 返回操作结果，成功则返回成功消息，失败则返回错误信息。操作结果使用CommonResult类表示。
     */
    @Override
    public CommonResult savePetAndAppointment(PetAndTimeDTO petAndTimeDTO) {
        try {
            Pet pet = petAndTimeDTO.getPet();
            long petId;
            // 如果宠物ID为空，则生成新的ID；否则使用提供的ID
            if (pet.getId() == null) {
                petId = getId();
            } else {
                petId = petAndTimeDTO.getPet().getId();
            }

            // 检查数据库中是否存在相同的宠物信息
            Pet petCheck = petMapper.selectById(pet.getId());
            if (petCheck == null) {
                // 当宠物信息不存在时，插入新的宠物信息和默认状态到数据库
                pet.setId(petId);
                petMapper.insert(pet);

                PetStatus petStatus = new PetStatus();
                // 设置宠物状态的初始值
                petStatus.setId(getId());
                petStatus.setPetId(petId);
                petStatus.setIsInject(0);
                petStatus.setIsShower(0);
                petStatus.setIsFeed(0);
                petStatusMapper.insert(petStatus);

                // 创建并插入新的预约信息到数据库
                Appointment appointment = new Appointment();
                appointment.setId(getId());
                appointment.setStartTime(petAndTimeDTO.getStartTime());
                appointment.setEndTime(petAndTimeDTO.getEndTime());
                appointment.setRoomId(petAndTimeDTO.getRoomId());
                appointment.setPetId(petId);
                appointmentMapper.insert(appointment);
            } else {
                // 当宠物信息已存在时，更新预约信息
                Appointment appointment = appointmentMapper.selectByPetId(petId);
                appointment.setStartTime(petAndTimeDTO.getStartTime());
                appointment.setEndTime(petAndTimeDTO.getEndTime());
                appointment.setRoomId(petAndTimeDTO.getRoomId());
                appointmentMapper.updateById(appointment);
            }

            // 记录操作日志
            LOGGER.info("添加宠物信息和预约信息成功");
            // 返回成功结果
            return CommonResult.success("添加宠物信息和预约信息成功");
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }



    /**
     * 根据用户id获取宠物信息
     *
     * @param id 用户id
     * @return 返回宠物信息列表，如果用户未认证或未找到相关宠物，则返回错误信息
     */
    @Override
    public CommonResult getByUserId(Long id) {
        try {
            // 尝试从SecurityContextHolder中获取当前认证的用户信息
            AdminUserDetails adminUserDetails = null;
            Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
            if (authentication != null && authentication.getPrincipal() instanceof AdminUserDetails) {
                adminUserDetails = (AdminUserDetails) authentication.getPrincipal();
            } else {
                // 如果无法获取到AdminUserDetails，表示用户未认证，返回未授权错误
                CommonResult.unauthorized(null);
            }

            // 根据AdminUserDetails中的用户名查询User信息
            QueryWrapper<User> userWrapper = new QueryWrapper<>();
            userWrapper
                    .eq("username", adminUserDetails.getUsername());
            User user = userMapper.selectOne(userWrapper);

            // 根据User的id查询其拥有的宠物列表
            QueryWrapper<Pet> wrapper = new QueryWrapper<>();
            wrapper
                    .eq("user_id", user.getId());
            List<Pet> pets = petMapper.selectList(wrapper);

            // 记录日志表示获取宠物信息成功
            LOGGER.info("根据id获取寄养宠物成功");

            // 返回宠物信息列表，如果查询成功
            return CommonResult.success(pets);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }


    /**
     * 删除寄养宠物
     *
     * @param id
     * @return
     */
    @Override
    public CommonResult removeByPetId(Long id) {
        //删除符合标准的预约
        QueryWrapper<Appointment> wrapper = new QueryWrapper<>();
        wrapper
                .eq("pet_id", id);
        Appointment appointment = appointmentMapper.selectOne(wrapper);
        if (appointment == null) {
            return CommonResult.failed("该宠物的预约不存在");
        }
        appointmentMapper.delete(wrapper);
        //删除对应的宠物状态
        QueryWrapper<PetStatus> wrapper1 = new QueryWrapper<>();
        wrapper1
                .eq("pet_id", id);
        petStatusMapper.delete(wrapper1);
        petMapper.deleteById(id);
        return CommonResult.success("删除寄养宠物成功");
    }

    @Override
    public Page<Pet> pagePet(Page<Pet> page) {
        try {
            // 尝试获取当前登录的管理员用户详情
            AdminUserDetails adminUserDetails = null;
            Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
            if (authentication != null && authentication.getPrincipal() instanceof AdminUserDetails) {
                adminUserDetails = (AdminUserDetails) authentication.getPrincipal();
            } else {
                // 若无管理员用户登录，则返回未授权错误
                CommonResult.unauthorized(null);
            }

            // 根据管理员用户详情查询对应的用户信息
            User user = userMapper.selectUserByUsername(adminUserDetails.getUsername());

            // 构建查询条件，限制为用户自己的宠物
            QueryWrapper<Pet> wrapper = new QueryWrapper<>();
            wrapper.eq("user_id", user.getId());

            // 如果是管理员用户，则查询所有寄养宠物，不加任何条件限制
            if (user.getIsAdmin() == 1) {
                wrapper = null;
            }

            // 执行分页查询
            Page<Pet> page2 = petMapper.selectPage(page, wrapper);

            // 遍历查询结果，设置每个宠物的寄养时间，并判断是否过期
            page.getRecords().forEach(pet -> {
                setPetDateAndRoom(pet);
            });

            return page2;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 根据宠物ID获取宠物信息。
     *
     * @param id 宠物的唯一标识符。
     * @return 返回匹配的宠物对象。如果找不到，则返回null。
     */
    @Override
    public Pet getByPetId(Long id) {
        // 通过ID从数据库中查询宠物
        Pet pet = petMapper.selectById(id);
        // 设置宠物的日期和房间信息
        setPetDateAndRoom(pet);
        return pet;
    }


    /**
     * 设置宠物的寄养日期和房间信息
     *
     * @param pet 宠物对象，需要更新寄养日期和房间信息
     */
    private void setPetDateAndRoom(Pet pet) {
        // 根据宠物ID查询寄养的开始和结束时间
        Map<String, Date> map = appointmentMapper.selectDate(pet.getId());
        Date startTime = map.get("start_time");
        Date endTime = map.get("end_time");
        pet.setStartTime(startTime);
        pet.setEndTime(endTime);

        // 判断当前时间是否在寄养日期范围内
        if (DateUtil.isIn(new Date(), startTime, endTime)) {
            pet.setIsValid(0); // 如果当前时间在寄养日期范围内，设置为未过期状态
        } else {
            pet.setIsValid(1); // 如果当前时间不在寄养日期范围内，设置为过期状态
        }

        // 查询宠物寄养的房间ID
        Long roomId = appointmentMapper.selectRoomId(pet.getId());
        pet.setRoomId(roomId);
    }


}
